/* Database.h
Michael Zahniser, 2008

Database of financial transactions.
*/

#ifndef __FINE_DATABASE_H__
#define __FINE_DATABASE_H__

#include "Date.h"
#include "Account.h"
#include "Transaction.h"

#include <map>
#include <vector>

using std::map;
using std::vector;



class Database {
public:
    // Load the database from the given input stream.
    void Load(istream &in);
    // Save the database to the given output stream.
    void Save(ostream &out) const;

    // If the given date contains wildcards, return the sum of all transactions matching the date, not
    // including any hidden accounts. If the date is a single day, return the balances of all accounts
    // at the beginning of that day, and include the effects of hidden accounts.
    // NOTE: The map that is returned is valid _only_ until the next query is made. Also note that this
    // function is not thread-safe.
    const map<string, Account> &Query(const Date &date);

    // Get a listing of all checks that have been drawn but not cashed.
    const map<string, Account> &Checks();

    // Get a reference to all accounts. The balance values are not valid.
    const map<string, Account> &Accounts();

    // List all transactions matching the given date.
    const vector<Transaction> &Transactions(const Date &date);
    // Get all transactions.
    const vector<Transaction> &Transactions();

    // Add a transaction to the database. The "from" and "to" values may be partial strings that should
    // be matched to existing account names. This function will _not_ create new accounts. The return value
    // is a string reporting which accounts were determined to be the best match.
    const string &AddTransaction(const Transaction &transaction);
    // Cancel the most recently added transaction.
    const string &CancelTransaction();

    // Add an account. Newly created accounts always have a balance of 0. The return value is a string
    // reporting whether the account was created successfully (it will not be if it already exists).
    const string &AddAccount(const string &account);

    // Set or clear a flag on an account. The return value is a string giving the account's flags.
    // If the flag string is empty, this reports all flags for the account.
    // If the string begins with a !, the flag is cleared instead of being set.
    const string &SetFlag(const string &account, const string &flag, bool set);
    // Set the account type.
    const string &SetType(const string &account, const string &type);


private:
    // Status message returned by the different functions.
    mutable string status;

    // This map stores the account traits and also stores the balances returned by each call to Query().
    map<string, Account> accounts;
    // This is a list of all transactions.
    vector<Transaction> transactions;
};

#endif
